package com.sojson.service.impl;

import java.util.HashSet;
import java.util.Set;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sojson.config.exception.TransErrorCode;
import com.sojson.config.exception.TransException;
import com.sojson.constant.Constant;
import com.sojson.constant.Lock;
import com.sojson.dao.MemberDao;
import com.sojson.dao.UserRoleDao;
import com.sojson.entity.po.Member;
import com.sojson.entity.po.UserRole;
import com.sojson.enums.core.ERoleType;
import com.sojson.result.bean.Status;
import com.sojson.service.AuthcService;
import com.sojson.util.StringUtil;
import com.sojson.util.file.FileDepotUtil;
import com.sojson.util.file.FileUtil;
import com.sojson.util.file.constant.ConstantFileFieldName;
import com.sojson.util.file.enums.EFileTable;
import com.sojson.util.pay.wx.WxUtil;
import com.sojson.util.pay.wx.bean.WxResult;
import com.sojson.util.security.springsecurity.service.CustomUserDetailsService;
import com.sojson.util.token.Token;
import com.sojson.util.token.TokenUtil;
import com.sojson.util.token.TokenVo;

/**
 * 认证Service实现类
 * 
 * @author liu
 * @date 2021-03-16
 */
@Service
public class AuthcServiceImpl implements AuthcService {

    @Autowired
    private AuthcServiceImpl authcServiceImpl;
    @Autowired
    private CustomUserDetailsService userDetailsService;
    @Resource
    private MemberDao memberDaoImpl;
    @Resource
    private UserRoleDao userRoleDaoImpl;

    /**
     * 帐号密码注册
     * 
     * @param token 认证用户Bean
     * @return
     * @throws Exception 
     */
    @Override
    public boolean pwdRegister(TokenVo token) throws Exception {
        Member member = token.getMember();

        // 插入初始化
        member.insertInit(token);
        member.encryptionPwd();

        synchronized (Lock.BALANCE_LOG) {
            synchronized (Lock.REGISTER_MOBILE_USERNAME) {
                return authcServiceImpl.pwdRegisterGo(token);
            }
        }
    }

    @Transactional
    public boolean pwdRegisterGo(TokenVo token) throws Exception {
        Member member = token.getMember();

        // 检查手机号是否存在
        String mobile = member.getMobile();
        if (StringUtil.isNotBlankObject(mobile)) {
            Set<String> hashSet = new HashSet<>();
            hashSet.add(TokenUtil.getRoleKey(token.getRoleId()));
            int countByMobile = memberDaoImpl.countByRoleMobile(hashSet, member.getMobile());
            // 如果存在就抛异常
            if (countByMobile > 0) {
                throw new TransException("手机号已存在");
            }
        }
        int insert = 0;
        // 查看此帐号是否存在
        int countByUsername = memberDaoImpl.countByUsername(member.getUsername());
        // 如果存在就抛异常
        if (countByUsername > 0) {
            throw new TransException(TransErrorCode.EXIST_USER);
        }

        // 处理其他业务
        Member registerStart = authcServiceImpl.registerStart(member);
        FileDepotUtil.insertSync(EFileTable.MEMBER.getCode(), ConstantFileFieldName.HEAD_IMG, member.getHeadImg());
        FileDepotUtil.insertSync(EFileTable.MEMBER.getCode(), ConstantFileFieldName.LABOR_CARD, member.getLaborCard());
        FileDepotUtil.insertSync(EFileTable.MEMBER.getCode(), ConstantFileFieldName.FOOD_CARD, member.getFoodCard());
        FileDepotUtil.insertSync(EFileTable.MEMBER.getCode(), ConstantFileFieldName.TELECOM_CARD,
            member.getTelecomCard());

        // 返回结果
        insert = memberDaoImpl.insert(member);
        if (insert < 1) {
            throw new TransException("注册用户失败！");
        }

        // 处理其他业务
        authcServiceImpl.registerEnd(token, registerStart);

        return insert > 0;
    }

    /**
     * 短信注册
     * 
     * @param token 认证用户Bean
     * @return
     * @throws Exception 
     */
    @Override
    public Member smsRegister(TokenVo token) throws Exception {
        Member member = token.getMember();

        // 插入初始化
        token.setDayGoOn(null);
        member.insertInit(token);
        member.setUsername(null);
        member.setWxUnionid(null);
        member.setPwd(Constant.USER_PASSWORD_DEFAULT_ENCODE);

        synchronized (Lock.BALANCE_LOG) {
            synchronized (Lock.REGISTER_MOBILE_USERNAME) {
                return authcServiceImpl.smsRegisterGo(token);
            }
        }
    }

    @Transactional
    public Member smsRegisterGo(TokenVo token) throws Exception {
        Member member = token.getMember();

        // 查看此手机号是否存在
        Set<String> hashSet = new HashSet<>();
        hashSet.add(ERoleType.USER.getKey());
        int countByMobile = memberDaoImpl.countByRoleMobile(hashSet, member.getMobile());
        // 如果存在就抛异常
        if (countByMobile > 0) {
            throw new TransException(TransErrorCode.EXIST_USER);
        }

        // 处理其他业务
        Member registerStart = authcServiceImpl.registerStart(member);

        // 返回结果
        int insert = memberDaoImpl.insert(member);
        if (insert < 1) {
            throw new TransException("注册用户失败！");
        }

        // 处理其他业务
        authcServiceImpl.registerEnd(token, registerStart);

        return member;
    }

    /**
     * 小程序注册
     * 
     * @param token 认证用户Bean
     * @return
     * @throws Exception 
     */
    @Override
    public Member xcxRegister(TokenVo token) throws Exception {
        Member member = token.getMember();

        // 用户不存在,注册用户
        // 插入初始化
        token.setDayGoOn(null);
        member.insertInit(token);
        member.setUsername(null);
        member.setMobile(null);
        member.setPwd(Constant.USER_PASSWORD_DEFAULT_ENCODE);

        synchronized (Lock.BALANCE_LOG) {
            return authcServiceImpl.xcxRegisterGo(token);
        }
    }

    @Transactional
    public Member xcxRegisterGo(TokenVo token) throws Exception {
        Member member = token.getMember();

        synchronized (Lock.BALANCE_LOG) {
            // 查看此微信号是否存在
            int countByWxUnionid = memberDaoImpl.countByWxUnionid(member.getWxUnionid());
            // 如果存在就抛异常
            if (countByWxUnionid > 0) {
                throw new TransException(TransErrorCode.EXIST_USER);
            }

            // 处理其他业务
            Member registerStart = authcServiceImpl.registerStart(member);

            // 返回结果
            int insert = memberDaoImpl.insert(member);
            if (insert < 1) {
                throw new TransException("注册失败！");
            }

            // 处理其他业务
            authcServiceImpl.registerEnd(token, registerStart);
        }
        return member;
    }

    /**
     * 统一的注册处理(插入前处理)
     * 
     * @param member
     * @return
     */
    @Transactional
    public Member registerStart(Member member) {
        // 设置上级ID
        // 查询上级对象
        String invitationCode = member.getInvitationCode();
        if (StringUtil.isBlankObject(invitationCode)) {
            return null;
        }
        Member findByInvitationCode = memberDaoImpl.findByInvitationCode(invitationCode);
        if (StringUtil.isBlankObject(findByInvitationCode)) {
            return null;
        }
        // 上级ID
        int id = findByInvitationCode.getId();
        // 清空邀请码
        member.setInvitationCode(null);
        if (StringUtil.isNotBlankObject(findByInvitationCode)) {
            member.setTopId(id);
        }
        return findByInvitationCode;
    }

    /**
     * 统一的注册处理(插入后处理)
     * 
     * @param token     当前用户信息
     * @param topMem    上级用户信息
     * @throws Exception
     */
    @Transactional
    public void registerEnd(TokenVo token, Member topMem) throws Exception {
        Member member = token.getMember();
        // 设置邀请码
        member.createInvitationCode();
        int updateById = memberDaoImpl.updateById(member);
        if (updateById < 1) {
            throw new TransException("设置邀请码失败！");
        }
        byte[] wxAcodeunLimit = WxUtil.getWxAcodeunLimit(member.getInvitationCode());
        String uploadingToThisLocalityDirectory = FileUtil.uploadToThisLocalityDirectory(wxAcodeunLimit,
            member.getNo() + "." + Constant.GENERATE_IMG_SUFFIX, "/xcxImg");
        if (StringUtil.isBlankObject(uploadingToThisLocalityDirectory)) {
            throw new TransException("小程序码生成失败！");
        }

        UserRole userRole = new UserRole();
        userRole.setRoleId(token.getRoleId());
        userRole.setUserId(member.getId());
        int insertRole = userRoleDaoImpl.insert(userRole);
        if (insertRole != 1) {
            throw new TransException("添加用户角色失败");
        }

        // if (StringUtil.isNotBlankObject(topMem)) {
        // // 添加佣金记录
        // BalanceLog balanceLog = new BalanceLog();
        // balanceLog.insertInitRegister("用户推广", member, topMem.getBalance());
        // String userId = member.getId() + "";
        // balanceLog.setOrderNo(userId);
        // balanceLog.setMark(userId);
        // balanceLogService.insert(balanceLog);
        //
        // // 修改佣金金额
        // Member mem = new Member();
        // mem.updateInit();
        // mem.setId(topMem.getId());
        // mem.setBalance(topMem.getBalance().add(balanceLog.getTotal()));
        // memberDaoImpl.updatePartialById(mem);
        // }
    }

    /**
     * 密码登录
     * 
     * @param token 认证用户Bean
     * @return
     * @throws Exception 
     */
    @Override
    public Token pwdLogin(TokenVo token) throws Exception {
        return authcServiceImpl.submitLogin(token);
    }

    /**
     * 短信登录
     * 
     * @param token 认证用户Bean
     * @return
     * @throws Exception 
     */
    @Override
    public Token smsLogin(TokenVo token) throws Exception {
        return authcServiceImpl.submitLogin(token);
    }

    /**
     * 微信小程序登录
     * 
     * @param token 认证用户Bean
     * @return
     * @throws Exception 
     */
    @Override
    public Object wxXcxLogin(TokenVo token) throws Exception {
        return authcServiceImpl.submitLogin(token);
    }

    /**
    * 登录
    *
    * @param user
    * @return
    * @throws Exception
    */
    public Token submitLogin(TokenVo user) throws Exception {
        return userDetailsService.submitLogin(user);
    }

    /**
     * 移动应用绑定微信
     * 
     * @param code 用户授权后的code
     * @return
     * @throws Exception 
     */
    @Override
    public int wxAppBindOpenid(String code) throws Exception {
        WxResult appAccessToken = WxUtil.getAppAccessToken(code);
        Status status = appAccessToken.getStatus();
        if (status.getCode() != TransErrorCode.SUCCESS.getCode()) {
            throw new TransException(status.getMsg());
        }

        Member member = new Member();
        member.setId(TokenUtil.getUserId());
        member.setOpenid(appAccessToken.getOpenid());
        return memberDaoImpl.updatePartialById(member);
    }

    /**
     * 小程序绑定微信
     * 
     * @param code 用户授权后的code
     * @return
     * @throws Exception 
     */
    @Override
    public int wxXcxBindOpenid(String code) throws Exception {
        // TODO
        WxResult result = WxUtil.xcxLogin(code);
        Integer userId = TokenUtil.getUserId();
        Member findById = memberDaoImpl.findById(userId);
        if (StringUtil.isNotBlankString(findById.getOpenid())) {
            return 0;
        }

        Member member = new Member();
        member.setId(userId);
        member.setOpenid(result.getOpenid());
        return memberDaoImpl.updatePartialById(member);
    }

}